package org.john.common.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Slf4j
public abstract class GzipUtil {

    private static final int BUFFER_SIZE = 8192;

    public static File unGzip(File file) {
        if (!file.exists() || file.isDirectory()) {
            return null;
        }
        if (!getExtension(file.getName()).equalsIgnoreCase("gz")) {
            log.error("File name must have extension of \".gz\"");
            return null;
        }
        File outputfile = new File(creatUnGzFileName(file));
        try (GZIPInputStream in = new GZIPInputStream(new FileInputStream(file)); FileOutputStream out = new FileOutputStream(outputfile)) {
            if (outputfile.exists()) {
                log.info("原文件存在，正在删除");
                boolean delete = outputfile.delete();
                log.info("原文件已经删除");
            }
            if (!outputfile.exists()) {
                final boolean newFile = outputfile.createNewFile();
            }
            log.info("开始解压文件");
            byte[] buf = new byte[BUFFER_SIZE];
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
            log.info("解压成功");
        } catch (IOException e) {
            log.error("解压文件" + file.getAbsolutePath() + "异常");
            log.error(e.getMessage(), e);
            return null;
        }
        return outputfile;
    }

    public static File gzip(List<File> files, String fileName) {
        Assertion.notEmpty(fileName, "压缩文件名必须设置。");
        String gzipFileFullName = null;
        for (File file : files) {
            if (!file.exists() || file.isDirectory()) {
                return null;
            }
            if (StringUtils.isEmpty(gzipFileFullName)) {
                gzipFileFullName = file.getAbsolutePath();
            }
        }
        assert gzipFileFullName != null;
        gzipFileFullName = gzipFileFullName.substring(0, gzipFileFullName.lastIndexOf(File.separator)) + File.separator + fileName;
        File gzipFile = new File(gzipFileFullName);
        if (gzipFile.exists()) {
            boolean delete = gzipFile.delete();
        }
        // 压缩文件
        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(gzipFile))) {
            for (File file : files) {
                try (FileInputStream fis = new FileInputStream(file)) {
                    ZipEntry entry = new ZipEntry(file.getName());
                    zos.putNextEntry(entry);
                    byte[] buffer = new byte[BUFFER_SIZE];
                    int len;
                    while (0 < (len = fis.read(buffer))) {
                        zos.write(buffer, 0, len);
                    }
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                    return null;
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return null;
        }
        return gzipFile;
    }

    public static File gzip(File file, String fileName) {
        if (!file.exists() || file.isDirectory()) {
            return null;
        }
        String gzipFileFullName = file.getAbsolutePath();
        if (StringUtils.isNotBlank(fileName)) {
            gzipFileFullName = gzipFileFullName.substring(0, gzipFileFullName.lastIndexOf(File.separator)) + File.separator + fileName;
        } else {
            gzipFileFullName = file.getAbsolutePath() + ".gz";
        }
        File gzipFile = new File(gzipFileFullName);
        if (gzipFile.exists()) {
            boolean delete = gzipFile.delete();
        }

        try (FileInputStream fis = new FileInputStream(file); GZIPOutputStream gos = new GZIPOutputStream(new FileOutputStream(gzipFile))) {
            byte[] buffer = new byte[BUFFER_SIZE];
            int len;
            while (0 < (len = fis.read(buffer))) {
                gos.write(buffer, 0, len);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return null;
        }

        return gzipFile;
    }

    /**
     * 默认，将解压缩文件解压到压缩文件所在目录下
     */
    private static String creatUnGzFileName(File file) {
        return file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf(".gz"));
    }

    /**
     * Used to extract and return the extension of a given file.
     *
     * @param f Incoming file to get the extension of
     * @return <code>String</code> representing the extension of the incoming file.
     */
    private static String getExtension(String f) {
        String ext = "";
        int i = f.lastIndexOf('.');

        if (i > 0 && i < f.length() - 1) {
            ext = f.substring(i + 1);
        }
        return ext;
    }
}